﻿using System;
using System.Windows;
using System.Windows.Browser;


namespace Jellyfish.jfDeepZoom
{

    /// <summary>
    /// Event MouseWheel
    /// </summary>
    public class MouseWheelEventArgs : EventArgs
    {
        private double delta;
        private bool handled = false;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="delta"></param>
        public MouseWheelEventArgs(double delta)
        {
            this.delta = delta;
        }
        /// <summary>
        /// movement of MouseWheel
        /// </summary>
        public double Delta
        {
            get { return this.delta; }
        }

        /// <summary>
        /// Handled
        /// </summary>
        public bool Handled
        {
            get { return this.handled; }
            set { this.handled = value; }
        }
    }

    /// <summary>
    /// MouseWheelHelper
    /// </summary>
    public class MouseWheelHelper
    {
        /// <summary>
        /// It raised when MouseWheel Move
        /// </summary>
        public event EventHandler<MouseWheelEventArgs> Moved;
        private static Worker worker;
        private bool isMouseOver = false;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="element">FrameworkElement</param>
        public MouseWheelHelper(FrameworkElement element)
        {

            if (MouseWheelHelper.worker == null)
                MouseWheelHelper.worker = new Worker();

            MouseWheelHelper.worker.Moved += this.HandleMouseWheel;

            element.MouseEnter += this.HandleMouseEnter;
            element.MouseLeave += this.HandleMouseLeave;
            element.MouseMove += this.HandleMouseMove;
        }

        /// <summary>
        /// Handles the mouse wheel.
        /// </summary>
        /// <param name="sender">Sender</param>
        /// <param name="args">The <see cref="Jellyfish.jfDeepZoom.MouseWheelEventArgs"/> instance containing the event data.</param>
        protected void HandleMouseWheel(object sender, MouseWheelEventArgs args)
        {
            if (this.isMouseOver)
                this.Moved(this, args);
        }

        private void HandleMouseEnter(object sender, EventArgs e)
        {
            this.isMouseOver = true;
        }

        private void HandleMouseLeave(object sender, EventArgs e)
        {
            this.isMouseOver = false;
        }

        private void HandleMouseMove(object sender, EventArgs e)
        {
            this.isMouseOver = true;
        }


        private class Worker
        {

            public event EventHandler<MouseWheelEventArgs> Moved;

            public Worker()
            {

                if (HtmlPage.IsEnabled)
                {
                    HtmlPage.Window.AttachEvent("DOMMouseScroll", this.HandleMouseWheel);
                    HtmlPage.Window.AttachEvent("onmousewheel", this.HandleMouseWheel);
                    HtmlPage.Document.AttachEvent("onmousewheel", this.HandleMouseWheel);
                }

            }

            protected void HandleMouseWheel(object sender, HtmlEventArgs args)
            {
                double delta = 0;

                ScriptObject eventObj = args.EventObject;

                if (eventObj.GetProperty("wheelDelta") != null)
                {
                    delta = ((double)eventObj.GetProperty("wheelDelta")) / 120;


                    if (HtmlPage.Window.GetProperty("opera") != null)
                        delta = -delta;
                }
                else if (eventObj.GetProperty("detail") != null)
                {
                    delta = -((double)eventObj.GetProperty("detail")) / 3;

                    if (HtmlPage.BrowserInformation.UserAgent.IndexOf("Macintosh") != -1)
                        delta = delta * 3;
                }

                if (delta != 0 && this.Moved != null)
                {
                    MouseWheelEventArgs wheelArgs = new MouseWheelEventArgs(delta);
                    this.Moved(this, wheelArgs);

                    if (wheelArgs.Handled)
                        args.PreventDefault();
                }
            }
        }
    }
}